import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class WebServer extends Thread {
	public static final int PORT = 3333;
	public static final int BUFFER_SIZE = 100;
	private Scheduler myScheduler;
	private Client myClient;
	private ServerSocket serverSocket;
	private SchedulerGUI myGUI;

	public WebServer(Scheduler newScheduler, SchedulerGUI newGUI){
		myScheduler = newScheduler;
		myGUI = newGUI;
		myClient=new Client();
		try {
			serverSocket= new ServerSocket(PORT);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("server is up");
	}

	@Override
	public void run() {
		try {

			while (true) {
				Socket s = serverSocket.accept();
				receiveMessage(s);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void receiveMessage(Socket socket) throws Exception {
		System.out.println("message received");
		ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
		FileOutputStream fos = null;
		Boolean ongoing=false;
		Boolean isFile =false;
		byte [] buffer = new byte[BUFFER_SIZE];

		// 1. Read file name or the first line.
		Object o = ois.readObject();

		if (o instanceof String) {
			if(((String) o).compareTo((Constants.OUTFILENAME))==0){// it is a out.txt file
				fos = new FileOutputStream(Constants.INFILENAME);
				ongoing=true;	// the scheduling is not done
				isFile= true;	// incoming message is a file
			}
			else if(((String) o).compareTo((Constants.FINALSCHEDULE))==0) {// it is a final schedule file
				fos = new FileOutputStream(Constants.FINALSCHEDULE);
				isFile= true;	// incoming message is a file
			}
			else if(((String) o).compareTo((Constants.NOCOMMONSCHEDULE))==0){ // no common schedule warning
				myGUI.updateSystemMessage(Constants.NOCOMMONSCHEDULE);
				myScheduler.setLockStatus(false);	// set it to be  not busy;
				myScheduler.schedulingCancel(); // tell other members that schedule cancel
			}
			else if (((String) o).compareTo((Constants.SCHEDULECANCEL))==0){ // schedule cancelled
				myGUI.updateSystemMessage(Constants.SCHEDULECANCEL);
				myScheduler.setLockStatus(false);	// set it to be  not busy;
			}
			else if (((String) o).contains("false")){ // a ready reply received
				String[] messageArray =((String) o).split(",");
				myScheduler.addReadyMember(messageArray[0]);
				myScheduler.memberLockStatus(false);
			}
			else if (((String) o).contains(Constants.BUSYCHECK)){	// status checking
				String[] messageArray = ((String) o).split(",");	// isolate the host ip
				myClient.returnStatus(messageArray[1],myScheduler.getIP(), myScheduler.getLockStatus());
				if(!myScheduler.getLockStatus()){ // if not busy
					myScheduler.setLockStatus(true);	// set it to be busy;
					myGUI.updateSystemMessage("you are currently involved in a meeting scheduling");
				}
			}
			else{  //meeting time
				myGUI.updateSystemMessage("meeting will be on the uncoming "+(String) o);
				// rewrite local available schedule file
				myScheduler.saveNewSelfSchedule((String) o);
				ongoing=false;	// done scheduling
				isFile=false;	// not a file
				myScheduler.setLockStatus(false); // reset lock
			}
		}
		else if (o instanceof Boolean){ //not ready
			myScheduler.memberLockStatus((Boolean) o);
		}
		else {
			throwException("Something is wrong");
		}
		if(isFile){ // if incoming message is a file
			// 2. Read file to the end.
			Integer bytesRead = 0;

			do {
				o = ois.readObject();

				if (!(o instanceof Integer)) {
					throwException("Something is wrong");
				}

				bytesRead = (Integer)o;

				o = ois.readObject();
				if (!(o instanceof byte[])) {
					throwException("Something is wrong");
				}
				buffer = (byte[])o;
				// 3. Write data to output file.
				fos.write(buffer, 0, bytesRead);
			} while (bytesRead == BUFFER_SIZE);
			fos.close();
			ois.close();
			System.out.println("Done saving");
			if(ongoing)	// more member in the list
				myScheduler.matchSchedule();
			else{		// it is the final schedule
				System.out.println("Final schedule arrives");
				myScheduler.bCastSchedule();
				myScheduler.setLockStatus(false); //reset lock
			}
		}
	}

	public static void throwException(String message) throws Exception {
		throw new Exception(message);
	}
}  